﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.Canonicalizers
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

namespace Microsoft.InfoCards
{
  internal sealed class Canonicalizers
  {
    private static ICanonicalizer s_binary;
    private static ICanonicalizer s_caseInsensitiveWithHashing;
    private static ICanonicalizer s_caseSensitiveWithHashing;
    private static ICanonicalizer s_binaryWithHashing;

    private Canonicalizers()
    {
    }

    public static ICanonicalizer CaseInsensitiveWithHashing
    {
      get
      {
        if (Canonicalizers.s_caseInsensitiveWithHashing == null)
          Canonicalizers.s_caseInsensitiveWithHashing = (ICanonicalizer) new Canonicalizers.CaseInsensitiveCanonicalizer(true, Encoding.Unicode, CultureInfo.InvariantCulture);
        return Canonicalizers.s_caseInsensitiveWithHashing;
      }
    }

    public static ICanonicalizer CaseSensitiveWithHashing
    {
      get
      {
        if (Canonicalizers.s_caseSensitiveWithHashing == null)
          Canonicalizers.s_caseSensitiveWithHashing = (ICanonicalizer) new Canonicalizers.CaseSensitiveCanonicalizer(true, Encoding.Unicode, CultureInfo.InvariantCulture);
        return Canonicalizers.s_caseSensitiveWithHashing;
      }
    }

    public static ICanonicalizer Binary
    {
      get
      {
        if (Canonicalizers.s_binary == null)
          Canonicalizers.s_binary = (ICanonicalizer) new Canonicalizers.BinaryCanonicalizer(false);
        return Canonicalizers.s_binary;
      }
    }

    public static ICanonicalizer BinaryWithHashing
    {
      get
      {
        if (Canonicalizers.s_binaryWithHashing == null)
          Canonicalizers.s_binaryWithHashing = (ICanonicalizer) new Canonicalizers.BinaryCanonicalizer(true);
        return Canonicalizers.s_binaryWithHashing;
      }
    }

    private delegate byte[] CanonicalizeObjectCallback(object dataToHash);

    private abstract class CanonicalizerBase : ICanonicalizer
    {
      private bool m_hashValue;

      public CanonicalizerBase(bool hashValue)
      {
        this.m_hashValue = hashValue;
      }

      public byte[] Canonicalize(object obj)
      {
        if (obj == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (obj));
        byte[] rawForm = this.GetRawForm(obj);
        if (!this.m_hashValue)
          return rawForm;
        byte[] data = new byte[HashUtility.HashBufferLength];
        HashUtility.SetHashValue(data, 0, rawForm);
        return data;
      }

      public abstract bool CanCanonicalize(object obj);

      protected abstract byte[] GetRawForm(object obj);
    }

    private class BinaryCanonicalizer : Canonicalizers.CanonicalizerBase
    {
      private Dictionary<Type, Canonicalizers.CanonicalizeObjectCallback> m_canonicalizers;

      public BinaryCanonicalizer(bool hashValue)
        : base(hashValue)
      {
        this.m_canonicalizers = new Dictionary<Type, Canonicalizers.CanonicalizeObjectCallback>();
        this.CreateCanonicalizers();
      }

      public override bool CanCanonicalize(object obj)
      {
        if (obj == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (obj));
        return this.m_canonicalizers.ContainsKey(obj.GetType());
      }

      private void CreateCanonicalizers()
      {
        this.m_canonicalizers.Add(typeof (short), new Canonicalizers.CanonicalizeObjectCallback(this.CanonicalizeInt16));
        this.m_canonicalizers.Add(typeof (ushort), new Canonicalizers.CanonicalizeObjectCallback(this.CanonicalizeUInt16));
        this.m_canonicalizers.Add(typeof (int), new Canonicalizers.CanonicalizeObjectCallback(this.CanonicalizeInt32));
        this.m_canonicalizers.Add(typeof (uint), new Canonicalizers.CanonicalizeObjectCallback(this.CanonicalizeUInt32));
        this.m_canonicalizers.Add(typeof (long), new Canonicalizers.CanonicalizeObjectCallback(this.CanonicalizeInt64));
        this.m_canonicalizers.Add(typeof (ulong), new Canonicalizers.CanonicalizeObjectCallback(this.CanonicalizeUInt64));
        this.m_canonicalizers.Add(typeof (byte), new Canonicalizers.CanonicalizeObjectCallback(this.CanonicalizeByte));
        this.m_canonicalizers.Add(typeof (byte[]), new Canonicalizers.CanonicalizeObjectCallback(this.CanonicalizeByteArray));
        this.m_canonicalizers.Add(typeof (string), new Canonicalizers.CanonicalizeObjectCallback(this.CanonicalizeString));
        this.m_canonicalizers.Add(typeof (Guid), new Canonicalizers.CanonicalizeObjectCallback(this.CanonicalizeGuid));
        this.m_canonicalizers.Add(typeof (GlobalId), new Canonicalizers.CanonicalizeObjectCallback(this.CanonicalizeGlobalId));
      }

      protected override byte[] GetRawForm(object obj)
      {
        return this.m_canonicalizers[obj.GetType()](obj);
      }

      private byte[] CanonicalizeGlobalId(object data)
      {
        if (data == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (data));
        return (Guid) ((GlobalId) data).ToByteArray();
      }

      private byte[] CanonicalizeGuid(object data)
      {
        if (data == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (data));
        return ((Guid) data).ToByteArray();
      }

      private unsafe byte[] CanonicalizeInt16(object data)
      {
        if (data == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (data));
        short num = (short) data;
        byte[] numArray = new byte[2];
        fixed (byte* numPtr = &numArray[0])
          *(short*) numPtr = num;
        return numArray;
      }

      private unsafe byte[] CanonicalizeUInt16(object data)
      {
        if (data == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (data));
        ushort num = (ushort) data;
        byte[] numArray = new byte[2];
        fixed (byte* numPtr = &numArray[0])
          *(short*) numPtr = (short) num;
        return numArray;
      }

      private unsafe byte[] CanonicalizeInt32(object data)
      {
        if (data == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (data));
        int num = (int) data;
        byte[] numArray = new byte[4];
        fixed (byte* numPtr = &numArray[0])
          *(int*) numPtr = num;
        return numArray;
      }

      private unsafe byte[] CanonicalizeUInt32(object data)
      {
        if (data == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (data));
        uint num = (uint) data;
        byte[] numArray = new byte[4];
        fixed (byte* numPtr = &numArray[0])
          *(int*) numPtr = (int) num;
        return numArray;
      }

      private unsafe byte[] CanonicalizeInt64(object data)
      {
        if (data == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (data));
        long num = (long) data;
        byte[] numArray = new byte[8];
        fixed (byte* numPtr = &numArray[0])
          *(long*) numPtr = num;
        return numArray;
      }

      private unsafe byte[] CanonicalizeUInt64(object data)
      {
        if (data == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (data));
        ulong num = (ulong) data;
        byte[] numArray = new byte[8];
        fixed (byte* numPtr = &numArray[0])
          *(long*) numPtr = (long) num;
        return numArray;
      }

      private byte[] CanonicalizeString(object data)
      {
        if (data == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (data));
        string s = (string) data;
        if (string.IsNullOrEmpty(s))
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (data));
        return Encoding.Unicode.GetBytes(s);
      }

      private byte[] CanonicalizeByte(object data)
      {
        if (data == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (data));
        return new byte[1]{ (byte) data };
      }

      private byte[] CanonicalizeByteArray(object data)
      {
        if (data == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (data));
        return (byte[]) data;
      }
    }

    private abstract class StringCanonicalizerBase : Canonicalizers.CanonicalizerBase
    {
      private static readonly Type[] s_validTypes = new Type[2]
      {
        typeof (string),
        typeof (Uri)
      };
      private Encoding m_encoding;
      private CultureInfo m_culture;

      protected StringCanonicalizerBase(bool hashValue, Encoding encoding, CultureInfo culture)
        : base(hashValue)
      {
        if (encoding == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (encoding));
        this.m_culture = culture != null ? culture : CultureInfo.InvariantCulture;
        this.m_encoding = encoding;
      }

      protected virtual Type[] SupportedTypes
      {
        get
        {
          return Canonicalizers.StringCanonicalizerBase.s_validTypes;
        }
      }

      public CultureInfo Culture
      {
        get
        {
          return this.m_culture;
        }
      }

      public Encoding Encoding
      {
        get
        {
          return this.m_encoding;
        }
      }

      public override bool CanCanonicalize(object obj)
      {
        if (obj == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (obj));
        if (this.SupportedTypes == null)
          return false;
        return -1 != Array.IndexOf<Type>(this.SupportedTypes, obj.GetType());
      }

      protected override byte[] GetRawForm(object obj)
      {
        return this.GetBytesFromString(obj.ToString());
      }

      protected abstract byte[] GetBytesFromString(string data);
    }

    private class CaseSensitiveCanonicalizer : Canonicalizers.StringCanonicalizerBase
    {
      public CaseSensitiveCanonicalizer(bool hashValue, Encoding encoding, CultureInfo culture)
        : base(hashValue, encoding, culture)
      {
      }

      protected override byte[] GetBytesFromString(string data)
      {
        return this.Encoding.GetBytes(data);
      }
    }

    private class CaseInsensitiveCanonicalizer : Canonicalizers.StringCanonicalizerBase
    {
      public CaseInsensitiveCanonicalizer(bool hashValue, Encoding encoding, CultureInfo culture)
        : base(hashValue, encoding, culture)
      {
      }

      protected override byte[] GetBytesFromString(string obj)
      {
        return this.Encoding.GetBytes(this.Culture.TextInfo.ToUpper(obj));
      }
    }
  }
}
